import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.simple.SimpleDataSource;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.SQLException;
import java.util.*;
import java.util.Date;

/**
 * 整合8大功能：
 * 1.历史对话记录（MySQL持久化） 2.对话系统（流式） 3.模型配置 4.提示词配置
 * 5.token配置 6.开场白配置 7.屏蔽词配置 8.退出系统
 */
public class AdvancedChatSystem {
    // -------------------------- 数据库配置（修改为你的MySQL信息） --------------------------
    private static final String DB_URL = "jdbc:mysql://localhost:3306/chat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
    private static final String DB_USER = "root";       // 你的MySQL用户名
    private static final String DB_PWD = "123456";      // 你的MySQL密码
    private static final String USER_ID = "10284711用户"; // 固定用户ID（可扩展为用户登录）

    // -------------------------- 全局变量（关键修改：全局数据源，避免查找默认配置） --------------------------
    private static SimpleDataSource DATA_SOURCE; // 全局自定义数据源
    private static String BEARER_TOKEN;          // Token配置（从DB加载）
    private static String MODEL;                 // 模型配置（从DB加载）
    private static int MAX_TOKENS;               // Token数量配置（从DB加载）
    private static double TEMPERATURE;           // 温度配置（从DB加载）
    private static String SYSTEM_PROMPT;         // 提示词配置（从DB加载）
    private static String GREETING;              // 开场白配置（从DB加载）
    private static Set<String> FORBIDDEN_WORDS;  // 屏蔽词配置（从DB加载）
    private static JSONArray messagesHistory;    // 内存中的历史对话（用于上下文关联）

    public static void main(String[] args) {
        try {
            // 1. 初始化自定义数据源（关键修复：不再依赖db.setting）
            initDataSource();
            // 2. 初始化数据库（创建表+插入默认数据）
            initDatabase();
            // 3. 加载所有配置到内存
            loadAllConfigs();
            // 4. 初始化历史对话（加入系统提示词，影响助手人设）
            initChatHistory();
            // 5. 启动对话系统
            startChat();
        } catch (Exception e) {
            System.err.println("系统启动失败：" + e.getMessage());
            e.printStackTrace();
        } finally {
            // 关闭数据源（程序退出时释放资源）
            if (DATA_SOURCE != null) {
                DATA_SOURCE.close();
            }
        }
    }

    // -------------------------- 关键修复：初始化自定义数据源 --------------------------
    private static void initDataSource() {
        try {
            DATA_SOURCE = new SimpleDataSource(DB_URL, DB_USER, DB_PWD);
            // 测试连接（可选，确保数据库能连通）
            DATA_SOURCE.getConnection().close();
            System.out.println("数据库连接成功！");
        } catch (SQLException e) {
            throw new RuntimeException("数据库连接失败，请检查配置：" + e.getMessage(), e);
        }
    }

    // -------------------------- 功能1：数据库初始化（自动建表+默认数据） --------------------------
    private static void initDatabase() throws SQLException {
        // 所有DB操作都显式传入自定义数据源（DATA_SOURCE），避免查找默认配置
        // 1. 创建模型配置表
        String createModelTable = "CREATE TABLE IF NOT EXISTS t_model_config (" +
                "id INT PRIMARY KEY AUTO_INCREMENT," +
                "model VARCHAR(50) NOT NULL COMMENT '模型名称（如x1）'," +
                "max_tokens INT NOT NULL DEFAULT 4096 COMMENT '最大生成Token数'," +
                "temperature DOUBLE NOT NULL DEFAULT 0.5 COMMENT '温度（0-1）'," +
                "create_time DATETIME DEFAULT CURRENT_TIMESTAMP," +
                "update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)";

        // 2. 创建提示词配置表
        String createPromptTable = "CREATE TABLE IF NOT EXISTS t_prompt_config (" +
                "id INT PRIMARY KEY AUTO_INCREMENT," +
                "system_prompt TEXT NOT NULL COMMENT '系统提示词（助手人设）'," +
                "create_time DATETIME DEFAULT CURRENT_TIMESTAMP," +
                "update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)";

        // 3. 创建Token配置表
        String createTokenTable = "CREATE TABLE IF NOT EXISTS t_token_config (" +
                "id INT PRIMARY KEY AUTO_INCREMENT," +
                "bearer_token VARCHAR(200) NOT NULL COMMENT '讯飞Bearer Token'," +
                "expire_time DATETIME COMMENT '过期时间（可为NULL）'," +
                "create_time DATETIME DEFAULT CURRENT_TIMESTAMP," +
                "update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)";

        // 4. 创建开场白配置表
        String createGreetingTable = "CREATE TABLE IF NOT EXISTS t_greeting_config (" +
                "id INT PRIMARY KEY AUTO_INCREMENT," +
                "greeting VARCHAR(500) NOT NULL COMMENT '首次对话开场白'," +
                "create_time DATETIME DEFAULT CURRENT_TIMESTAMP," +
                "update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)";

        // 5. 创建屏蔽词配置表
        String createForbiddenTable = "CREATE TABLE IF NOT EXISTS t_forbidden_words (" +
                "id INT PRIMARY KEY AUTO_INCREMENT," +
                "word VARCHAR(50) NOT NULL COMMENT '屏蔽词'," +
                "create_time DATETIME DEFAULT CURRENT_TIMESTAMP," +
                "UNIQUE KEY uk_word (word))";

        // 6. 创建对话历史表
        String createHistoryTable = "CREATE TABLE IF NOT EXISTS t_chat_history (" +
                "id BIGINT PRIMARY KEY AUTO_INCREMENT," +
                "user_id VARCHAR(50) NOT NULL COMMENT '用户ID'," +
                "role VARCHAR(20) NOT NULL COMMENT '角色（system/user/assistant）'," +
                "content TEXT NOT NULL COMMENT '对话内容'," +
                "create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '对话时间')";

        // 执行建表SQL（显式传入数据源）
        Db.use(DATA_SOURCE).execute(createModelTable);
        Db.use(DATA_SOURCE).execute(createPromptTable);
        Db.use(DATA_SOURCE).execute(createTokenTable);
        Db.use(DATA_SOURCE).execute(createGreetingTable);
        Db.use(DATA_SOURCE).execute(createForbiddenTable);
        Db.use(DATA_SOURCE).execute(createHistoryTable);

        // 插入默认数据（不存在时插入）
        insertDefaultData();
        System.out.println("数据库初始化完成！");
    }

    // 插入默认配置数据（显式传入数据源）
    private static void insertDefaultData() throws SQLException {
        // 1. 默认模型配置（不存在则插入）
        if (Db.use(DATA_SOURCE).queryNumber("SELECT COUNT(*) FROM t_model_config").intValue() == 0) {
            Db.use(DATA_SOURCE).insert(Entity.create("t_model_config")
                    .set("model", "x1")
                    .set("max_tokens", 4096)
                    .set("temperature", 0.5));
        }

        // 2. 默认提示词（助手人设：友好的智能助手）
        if (Db.use(DATA_SOURCE).queryNumber("SELECT COUNT(*) FROM t_prompt_config").intValue() == 0) {
            Db.use(DATA_SOURCE).insert(Entity.create("t_prompt_config")
                    .set("system_prompt", "你是一个友好、专业的智能助手，名为小火，专注于解答用户问题，语言简洁明了。"));
        }

        // 3. 默认Token（替换为你的讯飞Token，首次运行后可在数据库修改）
        if (Db.use(DATA_SOURCE).queryNumber("SELECT COUNT(*) FROM t_token_config").intValue() == 0) {
            Db.use(DATA_SOURCE).insert(Entity.create("t_token_config")
                    .set("bearer_token", "MZgLOGwIPGQRwzWQkSop:hBQOCxDcETmZzMMRhIzt") // 你的原有Token
                    .set("expire_time", null));
        }

        // 4. 默认开场白
        if (Db.use(DATA_SOURCE).queryNumber("SELECT COUNT(*) FROM t_greeting_config").intValue() == 0) {
            Db.use(DATA_SOURCE).insert(Entity.create("t_greeting_config")
                    .set("greeting", "你好！我是智能助手小火，有什么可以帮你的吗？"));
        }

        // 5. 默认屏蔽词（可在数据库添加更多）
        if (Db.use(DATA_SOURCE).queryNumber("SELECT COUNT(*) FROM t_forbidden_words").intValue() == 0) {
            List<Entity> forbiddenWords = new ArrayList<>();
            forbiddenWords.add(Entity.create("t_forbidden_words").set("word", "脏话"));
            forbiddenWords.add(Entity.create("t_forbidden_words").set("word", "敏感词1"));
            forbiddenWords.add(Entity.create("t_forbidden_words").set("word", "敏感词2"));
            Db.use(DATA_SOURCE).insert(forbiddenWords);
        }
    }

    // -------------------------- 功能3/4/5/6/7：加载所有配置到内存（显式传入数据源） --------------------------
    private static void loadAllConfigs() throws SQLException {
        // 1. 加载模型配置
        Entity modelEntity = Db.use(DATA_SOURCE).queryOne("SELECT * FROM t_model_config LIMIT 1");
        MODEL = modelEntity.getStr("model");
        MAX_TOKENS = modelEntity.getInt("max_tokens");
        TEMPERATURE = modelEntity.getDouble("temperature");

        // 2. 加载提示词配置
        Entity promptEntity = Db.use(DATA_SOURCE).queryOne("SELECT * FROM t_prompt_config LIMIT 1");
        SYSTEM_PROMPT = promptEntity.getStr("system_prompt");

        // 3. 加载Token配置
        Entity tokenEntity = Db.use(DATA_SOURCE).queryOne("SELECT * FROM t_token_config LIMIT 1");
        BEARER_TOKEN = tokenEntity.getStr("bearer_token");

        // 4. 加载开场白配置
        Entity greetingEntity = Db.use(DATA_SOURCE).queryOne("SELECT * FROM t_greeting_config LIMIT 1");
        GREETING = greetingEntity.getStr("greeting");

        // 5. 加载屏蔽词配置
        List<Entity> forbiddenEntities = Db.use(DATA_SOURCE).query("SELECT word FROM t_forbidden_words");
        FORBIDDEN_WORDS = new HashSet<>();
        for (Entity e : forbiddenEntities) {
            FORBIDDEN_WORDS.add(e.getStr("word"));
        }

        System.out.println("配置加载完成：");
        System.out.println("- 模型：" + MODEL + "，最大Token：" + MAX_TOKENS + "，温度：" + TEMPERATURE);
        System.out.println("- 系统提示词：" + SYSTEM_PROMPT);
        System.out.println("- 开场白：" + GREETING);
        System.out.println("- 屏蔽词数量：" + FORBIDDEN_WORDS.size());
    }

    // -------------------------- 功能1/2：初始化历史对话（含系统提示词） --------------------------
    private static void initChatHistory() {
        messagesHistory = new JSONArray();
        // 添加系统提示词（角色为system，放在最前面，影响所有对话）
        JSONObject systemMessage = new JSONObject();
        systemMessage.put("role", "system");
        systemMessage.put("content", SYSTEM_PROMPT);
        messagesHistory.put(systemMessage);
    }

    // -------------------------- 功能2：核心对话系统（整合所有功能） --------------------------
    private static void startChat() {
        Scanner scanner = new Scanner(System.in);
        // 输出开场白（功能6）
        System.out.println("小火：" + GREETING);
        System.out.println("提示：输入 'exit' 退出系统，输入内容将自动过滤敏感词");

        while (true) {
            try {
                // 接收用户输入
                System.out.print("\n你：");
                String userInput = scanner.nextLine().trim();

                // 功能8：退出系统
                if ("exit".equalsIgnoreCase(userInput)) {
                    System.out.println("小火：再见！欢迎下次使用～");
                    scanner.close();
                    return;
                }

                // 功能7：屏蔽词过滤
                if (containsForbiddenWord(userInput)) {
                    System.out.println("小火：你的输入包含敏感词，无法处理，请更换表述～");
                    continue;
                }

                // 构建用户消息，添加到内存历史记录
                JSONObject userMessage = new JSONObject();
                userMessage.put("role", "user");
                userMessage.put("content", userInput);
                messagesHistory.put(userMessage);

                // 保存用户消息到数据库（功能1：历史对话持久化）
                saveChatHistory(USER_ID, "user", userInput);

                // 发送请求到讯飞API（流式响应）
                sendStreamRequest();

            } catch (Exception e) {
                System.err.println("对话异常：" + e.getMessage());
                // 移除当前轮次的用户消息（避免历史记录污染）
                if (messagesHistory.size() > 1) { // 保留system消息，只移除当前user消息
                    messagesHistory.remove(messagesHistory.size() - 1);
                }
            }
        }
    }

    // -------------------------- 功能7：屏蔽词检测 --------------------------
    private static boolean containsForbiddenWord(String input) {
        for (String word : FORBIDDEN_WORDS) {
            if (input.contains(word)) {
                return true;
            }
        }
        return false;
    }

    // -------------------------- 功能1：保存对话历史到MySQL（显式传入数据源） --------------------------
    private static void saveChatHistory(String userId, String role, String content) throws SQLException {
        Db.use(DATA_SOURCE).insert(Entity.create("t_chat_history")
                .set("user_id", userId)
                .set("role", role)
                .set("content", content)
                .set("create_time", new Date()));
    }

    // -------------------------- 功能2：流式请求讯飞API（核心） --------------------------
    private static void sendStreamRequest() throws Exception {
        String url = "https://spark-api-open.xf-yun.com/v2/chat/completions";

        // 构建请求参数（整合模型配置、历史对话）
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("user", USER_ID);
        jsonObject.put("model", MODEL);
        jsonObject.put("messages", messagesHistory);
        jsonObject.put("stream", true);
        jsonObject.put("max_tokens", MAX_TOKENS);
        jsonObject.put("temperature", TEMPERATURE);

        // 配置HTTP请求
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
        con.setRequestProperty("Authorization", "Bearer " + BEARER_TOKEN); // Token从配置加载
        con.setDoOutput(true);

        // 发送请求体
        OutputStream os = con.getOutputStream();
        os.write(jsonObject.toString().getBytes("UTF-8"));
        os.flush();
        os.close();

        // 处理响应状态码
        int responseCode = con.getResponseCode();
        if (responseCode != 200) {
            throw new RuntimeException("API请求失败，状态码：" + responseCode);
        }

        // 流式读取响应
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
        String inputLine;
        StringBuilder assistantContent = new StringBuilder(); // 拼接助手完整回复

        System.out.print("小火：");
        while ((inputLine = in.readLine()) != null) {
            String line = inputLine.trim();
            if (line.isEmpty()) continue;
            if (line.contains("[DONE]")) break;

            // 解析JSON响应
            String jsonStr = line.startsWith("data:") ? line.substring("data:".length()).trim() : line;
            if (jsonStr.isEmpty()) continue;

            try {
                Object parse = JSON.parse(jsonStr);
                if (parse instanceof Map) {
                    Map<?, ?> map = (Map<?, ?>) parse;
                    List<?> choices = (List<?>) map.get("choices");
                    if (choices != null && !choices.isEmpty()) {
                        Map<?, ?> choiceMap = (Map<?, ?>) choices.get(0);
                        Map<?, ?> delta = (Map<?, ?>) choiceMap.get("delta");
                        if (delta != null && delta.containsKey("content")) {
                            String content = (String) delta.get("content");
                            System.out.print(content);
                            assistantContent.append(content);
                        }
                    }
                }
            } catch (Exception e) {
                System.err.println("\n解析响应片段失败：" + jsonStr);
            }
        }
        in.close();

        // 保存助手回复到内存历史和数据库
        if (assistantContent.length() > 0) {
            JSONObject assistantMessage = new JSONObject();
            assistantMessage.put("role", "assistant");
            assistantMessage.put("content", assistantContent.toString());
            messagesHistory.put(assistantMessage);
            saveChatHistory(USER_ID, "assistant", assistantContent.toString());
        }
    }
}